package com.jia.explore.genal.others;
/**
 * 位1的个数
 * 编写一个函数，输入是一个无符号整数，返回其二进制表达式中数字位数为 ‘1’ 的个数（也被称为汉明重量）。

 

示例 1：

输入：00000000000000000000000000001011
输出：3
解释：输入的二进制串 00000000000000000000000000001011 中，共有三位为 '1'。
示例 2：

输入：00000000000000000000000010000000
输出：1
解释：输入的二进制串 00000000000000000000000010000000 中，共有一位为 '1'。
示例 3：

输入：11111111111111111111111111111101
输出：31
解释：输入的二进制串 11111111111111111111111111111101 中，共有 31 位为 '1'。
 

提示：

请注意，在某些语言（如 Java）中，没有无符号整数类型。在这种情况下，输入和输出都将被指定为有符号整数类型，并且不应影响您的实现，因为无论整数是有符号的还是无符号的，其内部的二进制表示形式都是相同的。
在 Java 中，编译器使用二进制补码记法来表示有符号整数。因此，在上面的 示例 3 中，输入表示有符号整数 -3。
 

进阶:
如果多次调用这个函数，你将如何优化你的算法？
 * @author Administrator
 *
 */
public class Pro01 {
    public int hammingWeight2(int n) {
        return Integer.bitCount(n);
    }
    public int hammingWeight3(int n) {
    	int result = 0;
    	for(int i = 0; i < 32; i++) {
    		
    		if((n & (1 << i)) != 0) {
    			++result;
    		}
    	}
    	return result;
    }
    /**
     * //方法2：O(m),m为n的二进制的位数
	//减1操作将最右边的符号从0变到1，从1变到0，与操作将会移除最右端的1。如果最初n有X个1，那么经过X次这样的迭代运算，n将减到0。
     * @param n
     * @return
     */
    public int hammingWeight4(int n) {
    	int result = 0;
    	while(n!=0) {
    		n = n & (n -1);
    		++result;
    	}
    	return result;
    }
	// 方法3：汉明重量，O(1)
	//https://blog.csdn.net/sword52888/article/details/86513023 超详细解释
	//但要注意溢出问题，有可能报错，需要将溢出的进行处理！！！
	//0x55555555 == = >> 0101 0101 0101 0101 0101 0101 0101 0101，每两位为一组
	//0x33333333 == = >> 0011 0011 0011 0011 0011 0011 0011 0011，每四位为一组
	//0x0F0F0F0F == = >> 0000 1111 0000 1111 0000 1111 0000 1111，每八位为一组
	//0x01010101 == = >> 0000 0001 0000 0001 0000 0001 0000 0001，将4组8位累加，刚好是32位的前8位，后面24位可以舍去，前面溢出的更可以舍去
	int hammingWeight(int i)
	{
		i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
		i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
		i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
		i = (i * (0x01010101) >> 24);
		return i;
	}
}
